package interfaccia;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;

import fsmCore.*;

public class VisualizzaSimulazione implements ActionListener {
	/*@invariant s !=null
	  @
	 */
	
	private static final int COLUMN_WIDTH=190;
	private static final int COLUMN_HEIGTH=20;
	private static final int NUMERO_RIGHE=15;
	private static final int NUMERO_COLONNE=7;
	private static final String [] INTESTAZIONE={"ISTANTE CORRENTE","STATO CORRENTE","TRANSIZIONE EFFETTUATA","TRANSIZIONE IN ATTO","STATO CORRENTE","TRANSIZIONE EFFETTUATA","TRANSIZIONE IN ATTO","MACCHINA NUMERO 1","MACCHINA NUMERO 2"};
	private static final int NUMERO_MACCHINE=2;	
	
	private Simulazione s;
	private JFrame finestra;
	private JPanel [] statoSistema;
	private JPanel pannelloStato;
	
	private JPanel pannelloPulsanti;
	private JButton next;
	private JButton[] infoTransInAtto;
	private JButton[] infoTransEffettuata;
	
	
	
	
	
	public VisualizzaSimulazione(Macchina [] _fsm) {
		s= new Simulazione(_fsm);
		s.impostaStatiIniziali();
		
		finestra = new JFrame("Simulazione");//crea la finestra
		finestra.setLayout(new BorderLayout());
		finestra.setBounds(10, 10,COLUMN_WIDTH*7+10,400);
		
		pannelloStato=new JPanel();//crea il pannnello contenente lo stato della simulazione
		statoSistema= new JPanel[NUMERO_RIGHE];
		creaPannelloStato();
		setPannelloStato();
		finestra.add(pannelloStato,BorderLayout.NORTH);
		
		pannelloPulsanti = new JPanel();//crea il pannello contenente i pulsanti
		creaPannelloPulsanti();
		finestra.add(pannelloPulsanti,BorderLayout.SOUTH);
		
		
		
	}
	
	public void showSimulazione(){
		
		finestra.setVisible(true);
	}
	
	private void creaStatoSistema(){
				
		for(int j=0;j<NUMERO_RIGHE;j++){
			statoSistema[j]=new JPanel();
			statoSistema[j].setLayout(new GridLayout(1,7));
			JLabel[] l=new JLabel[NUMERO_COLONNE];
			
			for(int i=0;i<NUMERO_COLONNE;i++){
				l[i]=new JLabel();
				l[i].setBounds(0, 0, COLUMN_WIDTH, COLUMN_HEIGTH);
				statoSistema[j].add(l[i]);
			}
		
		}
		
		JLabel intestazione;
		statoSistema[0].setBackground(Color.DARK_GRAY);//crea la prima riga di intestazione
		statoSistema[1].setBackground(Color.DARK_GRAY);
		
		intestazione=(JLabel)statoSistema[0].getComponent(1);
		intestazione.setText(INTESTAZIONE[7]);
		intestazione.setForeground(Color.YELLOW);
		intestazione=(JLabel)statoSistema[0].getComponent(4);
		intestazione.setText(INTESTAZIONE[8]);
		intestazione.setForeground(Color.YELLOW);
			
		for(int i=0;i<NUMERO_COLONNE;i++){
			intestazione=(JLabel)statoSistema[1].getComponent(i);//crea la seconda riga di intestazione
			intestazione.setText(INTESTAZIONE[i]);
			intestazione.setForeground(Color.YELLOW);
		}
		
		statoSistema[2].setBorder(new LineBorder(Color.black));//crea un riquadro intorno allo stato corrente del sistema,la riga numero 2
		statoSistema[2].setBackground(Color.green);
		
	}
	
	private void creaPannelloStato(){
		pannelloStato.setLayout(new GridLayout(NUMERO_RIGHE,NUMERO_COLONNE));
		pannelloStato.setBounds(0, 0, NUMERO_COLONNE*COLUMN_WIDTH, NUMERO_RIGHE*COLUMN_HEIGTH);
		
		creaStatoSistema();
		
		for(int i=0;i<NUMERO_RIGHE;i++)
			pannelloStato.add(statoSistema[i]);	
		
	}
	
	/*Da settare con i parametri della macchina quando ci sono i metodi
	 * 
	 * */
	
	private void setPannelloStato(){
		JLabel labelCorrente;
		JLabel labelPrecedente;
		
		for(int i=NUMERO_RIGHE-1;i>2;i--){
	
			for(int j=0;j<NUMERO_COLONNE;j++){
				labelCorrente=(JLabel)statoSistema[i-1].getComponent(j);
				labelPrecedente=(JLabel)statoSistema[i].getComponent(j);
				labelPrecedente.setText(labelCorrente.getText());
			}
			
		}	
		labelCorrente=(JLabel)statoSistema[2].getComponent(0);//assegna il valore all'etichetta dell'istante corrente
		labelCorrente.setText(Integer.toString(s.getIstanteCorrente()));
		
		for(int i=0;i<NUMERO_MACCHINE;i++){//assegna alle etichette i nuovi valori dei parametri delle fsm aggiornati all'istante corrente
			labelCorrente=(JLabel)statoSistema[2].getComponent(1+(3*i));
			labelCorrente.setText(s.getFsm()[i].getStatoCorrente().getNome());
			labelCorrente=(JLabel)statoSistema[2].getComponent(2+(3*i));
		
			if(s.getTransEffettuata()[i]!=null)
				labelCorrente.setText(s.getTransEffettuata()[i].getNome());
			else
				labelCorrente.setText("---");
		
			labelCorrente=(JLabel)statoSistema[2].getComponent(3+(3*i));
			if(s.getTransInAtto()[i]!=null)
				labelCorrente.setText(s.getTransInAtto()[i].getNome());
			else
				labelCorrente.setText("---");
			}
		
		
		
		
	}
	
	private void creaPannelloPulsanti(){
		pannelloPulsanti.setLayout(new FlowLayout());
		next=new JButton("Next");
		next.addActionListener(this);//gestione degli eventi
		pannelloPulsanti.add(next);
		
		
		JPanel [] fsm=new JPanel[NUMERO_MACCHINE];
		infoTransInAtto=new JButton[NUMERO_MACCHINE];
		infoTransEffettuata=new JButton[NUMERO_MACCHINE];
		
		for(int i=0;i<NUMERO_MACCHINE;i++){
			fsm[i]=new JPanel(new FlowLayout());	
			fsm[i].setBorder(new TitledBorder("Macchina numero "+(1+i)));
			
			infoTransEffettuata[i]=new JButton("Info transizione effettuata");
			infoTransInAtto[i]=new JButton("Info transizione in atto");
			
			infoTransEffettuata[i].addActionListener(this);
			infoTransInAtto[i].addActionListener(this);
			
			fsm[i].add(infoTransEffettuata[i]);
			fsm[i].add(infoTransInAtto[i]);
			pannelloPulsanti.add(fsm[i]);
			
		}
		setPulsantiEnabled();//assicura che sia rispettata la precondizione del metodo actionPerformed(action event e)
		
	}
	
	/*
	 *testare se funziona corretamente 
	 */
	private void setPulsantiEnabled(){
		for(int i=0; i<NUMERO_MACCHINE;i++){
			
			if(s.getTransEffettuata()[i]==null)
				infoTransEffettuata[i].setEnabled(false);
			else
				infoTransEffettuata[i].setEnabled(true);
			
			if(s.getTransInAtto()[i]==null)
				infoTransInAtto[i].setEnabled(false);
			else
				infoTransInAtto[i].setEnabled(true);
		}
			
		
	}
	
	
	public Simulazione getS() {
		return s;
	}

	public void setS(Simulazione s) {
		this.s = s;
	}

	@Override
	/*da testare quando è pronta simulazione 
	 * ogni tasto
	 * */
	/*@
	 *@ requires \for all int i; s.getTransEffettuata()[i] !=null && s.getTransInAtto()[i] !=null
	 */
	public void actionPerformed(ActionEvent e) {
		Object click =e.getSource();
		
		if(click==next){
			if(!s.sistemaBloccato()){
			s.eseguiIterazione();
			setPannelloStato();
			setPulsantiEnabled();//assicura che sia rispettata la precondizione alla prossima chiamata
			}
			else if(s.deadlock())
				JOptionPane.showMessageDialog(null, "IL sistema e' in Deadlockl\n Simulazione terminata","Error",JOptionPane.ERROR_MESSAGE);
			
			else
				JOptionPane.showMessageDialog(null, "Simulazione terminata","END",JOptionPane.INFORMATION_MESSAGE);
		}
		else{
		for (int i=0;i<2;i++){
		
			if(click==infoTransEffettuata[i]){
				JOptionPane.showMessageDialog(null, s.getTransEffettuata()[i].toStringDet(), "Info transizione effettuata", JOptionPane.INFORMATION_MESSAGE);
			}else if (click==infoTransInAtto[i]){
				JOptionPane.showMessageDialog(null, s.getTransInAtto()[i].toStringDet(), "Info transizione in Atto", JOptionPane.INFORMATION_MESSAGE);
			}
		}
		}
		
	}
}
	

	
	

